package com.seed.core.query;

import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryTable;
import com.seed.core.column.Column;
import com.seed.core.enumeration.PropertyType;
import com.seed.core.pojo.Join;
import com.seed.core.pojo.OrderBy;
import com.seed.core.pojo.seed.Relation;
import com.seed.core.pojo.seed.Seed;
import com.seed.core.query.pojo.Ordered;
import com.seed.util.StrKit;
import com.seed.util.SeedKit;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

public class SeedOrdered {
    private final Map<String, OrderBy> orders = new LinkedHashMap<>();
    private final Map<String, Join> leftJoins = new LinkedHashMap<>(); // 表关联对象
    private final Map<String, Ordered> fillOrdereds = new HashMap<>(); // fill对象使用

    public SeedOrdered(Seed selfSeed, Map<String, Ordered> ordereds) {
        init(null, selfSeed, ordereds);
    }

    private void init(String basePath, Seed selfSeed, Map<String, Ordered> ordereds) {
        String selfTableAlias = StrKit.selfTableAlias(basePath);
        QueryTable selfTable = new QueryTable(selfSeed.getTableName()).as(selfTableAlias);
        for(Map.Entry<String, Ordered> entry: ordereds.entrySet()) {
            String crossOrColumn = entry.getKey();
            String finalPath = StrKit.concat(basePath, crossOrColumn);
            Ordered value = entry.getValue();
            PropertyType propertyType = value.getType();
            switch (propertyType) {
                case none -> {
                    Column nameColumn = SeedKit.getNameColumn(selfSeed);
                    QueryColumn column = new QueryColumn(selfTable, nameColumn.getName());
                    String finalColumn = StrKit.concat(basePath, nameColumn.getName());
                    orders.put(finalColumn, new OrderBy(column, value.getValue()));
                }
                case asterisk -> {
                    Map<String, Column> columns = selfSeed.getColumns();
                    for (Column column: columns.values()) {
                        String columName = column.getName();
                        QueryColumn queryColumn = new QueryColumn(selfTable, columName);
                        String finalColumn = StrKit.concat(basePath, columName);
                        orders.put(finalColumn, new OrderBy(queryColumn, value.getValue()));
                    }
                }
                case column -> {
                    QueryColumn column = new QueryColumn(selfTable, ((Column) value.getProperty()).getName());
                    orders.put(finalPath, new OrderBy(column, value.getValue()));
                }
                case hasOne, belongsTo -> {
                    Relation relation = (Relation) value.getProperty();
                    Seed targetSeed = relation.targetSeed();
                    String targetTableAlias = StrUtil.toCamelCase(finalPath);
                    QueryTable targetTable = new QueryTable(targetSeed.getTableName()).as(targetTableAlias);

                    QueryCondition on = relation.getQueryCondition(basePath, crossOrColumn);
                    leftJoins.put(finalPath, new Join(targetTable, on));
                    init(finalPath, targetSeed, value);
                }
                default -> fillOrdereds.put(finalPath, value);
            }
        }
    }

    public Map<String, OrderBy> getOrders() {
        return orders;
    }

    public Map<String, Join> getLeftJoins() {
        return leftJoins;
    }

    public Ordered getFillOrdered(String key) {
        return fillOrdereds.get(key);
    }
}
